package cn.donting.jme.edit.ui.scenetree;

import cn.donting.jme.edit.EditorState;
import cn.donting.jme.edit.event.EventManager;
import cn.donting.jme.edit.event.SelectSpatialEvent;
import cn.donting.jme.edit.ui.inspector.InspectorView;
import cn.donting.jme.edit.ui.scenetree.meum.TreeContextMenu;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import lombok.extern.slf4j.Slf4j;

import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;

@Slf4j
public class SceneTreeNodeView implements Initializable {

    @FXML
    public TreeView treeView;
    @FXML
    public ScrollPane scrollPane;

    private Node rootNode;

    private TreeContextMenu contextMenu;

    private static SceneTreeNodeView sceneTreeNodeView;

    public SceneTreeNodeView() {
        if (sceneTreeNodeView != null) {
            log.error("不允许初始化多个sceneTreeNodeView");
        }
        sceneTreeNodeView = this;
    }

    public static SceneTreeNodeView getInstance() {
        return sceneTreeNodeView;
    }

    public void setRootNode(Node rootNode) {
        this.rootNode = rootNode;
        upDateTree();
    }

    /**
     * 更新root 节点树
     */
    @FXML
    public void upDateTree() {
        SpatialTreeItem spatialTreeItem = creatTreeItem(rootNode);
        treeView.setRoot(spatialTreeItem);
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        contextMenu = new TreeContextMenu(this);
        contextMenu.setMinSize(200, 200);
        treeView.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
            public void handle(MouseEvent event) {
                if (!event.getButton().equals(MouseButton.SECONDARY)) {
                    return;
                }
                javafx.scene.Node node = event.getPickResult().getIntersectedNode();
                //给node对象添加下来菜单；
                contextMenu.show(node, event.getScreenX() + 2, event.getScreenY() + 2);
            }
        });
        treeView.getSelectionModel().getSelectedItems().addListener(new ListChangeListener() {
            @Override
            public void onChanged(Change c) {
                ObservableList selectedItems = treeView.getSelectionModel().getSelectedItems();
                if (selectedItems.size() == 1) {
                    SpatialTreeItem spatialTreeItem = (SpatialTreeItem) selectedItems.get(0);
                    EventManager.pushEvent(new SelectSpatialEvent(spatialTreeItem.getSpatial(), treeView));

                }
                if (selectedItems.size() == 0) {
                    EventManager.pushEvent(new SelectSpatialEvent(null, treeView));
                }

            }
        });

        treeView.setPrefWidth(scrollPane.getWidth() - 4);
        treeView.setPrefHeight(scrollPane.getHeight() - 4);
        scrollPane.widthProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                treeView.setPrefWidth(newValue.doubleValue() - 4);
            }
        });
        scrollPane.heightProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                treeView.setPrefHeight(newValue.doubleValue() - 4);
            }
        });
    }

    /**
     * 往选中的节点 添加一个 Spatial
     */
    public void addSpatialToSelectNode(Spatial spatial) {
        SpatialTreeItem spatialTreeItem = creatTreeItem(spatial);
        SpatialTreeItem selectedItem=(SpatialTreeItem)treeView.getSelectionModel().getSelectedItem();
        if(selectedItem.getSpatial() instanceof Node){
            EditorState.getJmeEditSceneApp().enqueue(() -> {
                selectedItem.getChildren().add(spatialTreeItem);
                ((Node) selectedItem.getSpatial()).attachChild(spatial);
            });
            return;
        }
        log.error("添加场景spatial错误，选中的目标不是一个 Node");
    }

    /**
     * 递归创建子树
     * @param spatial
     * @param prent
     */
    private void creatTreeItem(Spatial spatial, TreeItem prent) {
        SpatialTreeItem spatialItem = new SpatialTreeItem(spatial);
        prent.getChildren().add(spatialItem);
        if (spatial instanceof Node) {
            List<Spatial> children = ((Node) spatial).getChildren();
            for (Spatial child : children) {
                creatTreeItem(child, spatialItem);
            }
        }
    }

    /**
     * 从spatial 创建一个SpatialTreeItem 树
     * @param spatial
     * @return
     */
    private SpatialTreeItem creatTreeItem(Spatial spatial) {
        SpatialTreeItem spatialItem = new SpatialTreeItem(spatial);
        if (spatial instanceof Node) {
            List<Spatial> children = ((Node) spatial).getChildren();
            for (Spatial child : children) {
                creatTreeItem(child, spatialItem);
            }
        }
        return spatialItem;
    }

    /**
     * 删除选中的节点
     */
    public void deleteSelectNode() {
        SpatialTreeItem selectedItem = (SpatialTreeItem) treeView.getSelectionModel().getSelectedItem();
        selectedItem.getParent().getChildren().remove(selectedItem);
        Spatial spatial = selectedItem.getSpatial();
        spatial.getParent().detachChild(spatial);
        treeView.getSelectionModel().clearSelection();
    }

    /**
     * 获取选中的 Spatial
     * @return
     */
    public Spatial getSelectSpatial() {
        SpatialTreeItem selectedItem = (SpatialTreeItem) treeView.getSelectionModel().getSelectedItem();
        if(selectedItem==null){
            return null;
        }
        Spatial spatial = selectedItem.getSpatial();
        return spatial;
    }

    /**
     * 移动选中的 Spatial到目标节点
     *
     * @param moveSpatialTreeItem 要移动的 moveSpatialTreeItem
     */
    public void moveSelectSpatial(SpatialTreeItem moveSpatialTreeItem) {
        SpatialTreeItem selectedItem = (SpatialTreeItem) treeView.getSelectionModel().getSelectedItem();
        if (selectedItem.getSpatial() instanceof Node) {
            //treeView 移动
            moveSpatialTreeItem.getParent().getChildren().remove(moveSpatialTreeItem);
            selectedItem.getChildren().add(moveSpatialTreeItem);
            //node 移动
            moveSpatialTreeItem.getSpatial().getParent().detachChild(moveSpatialTreeItem.getSpatial());
            ((Node) selectedItem.getSpatial()).attachChild(moveSpatialTreeItem.getSpatial());
        }

    }

}
